package com.uwlaser.modules.system.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.uwlaser.http.exception.HttpException;
import com.uwlaser.socket.exception.TcpSocketException;
import com.uwlaser.utils.MyHttpUtil;
import com.uwlaser.utils.enums.DictValueEnum;
import lombok.AllArgsConstructor;
import com.uwlaser.base.PageInfo;
import com.uwlaser.base.QueryHelpMybatisPlus;
import com.uwlaser.base.impl.CommonServiceImpl;
import com.uwlaser.utils.ConvertUtil;
import com.uwlaser.utils.PageUtil;
import com.uwlaser.modules.system.domain.SysExternalHttpLog;
import com.uwlaser.modules.system.service.SysExternalHttpLogService;
import com.uwlaser.modules.system.service.dto.SysExternalHttpLogDto;
import com.uwlaser.modules.system.service.dto.SysExternalHttpLogQueryParam;
import com.uwlaser.modules.system.service.mapper.SysExternalHttpLogMapper;
import org.mortbay.util.ajax.JSON;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
// 默认不使用缓存
//import org.springframework.cache.annotation.CacheConfig;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import java.util.*;

/**
* @author QZK
* @date 2022-12-07
*/
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = SysExternalHttpLogService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class SysExternalHttpLogServiceImpl extends CommonServiceImpl<SysExternalHttpLogMapper, SysExternalHttpLog> implements SysExternalHttpLogService {

    // private final RedisUtils redisUtils;
    private final SysExternalHttpLogMapper sysExternalHttpLogMapper;

    @Override
    public PageInfo<SysExternalHttpLogDto> queryAll(SysExternalHttpLogQueryParam query, Pageable pageable) {
        IPage<SysExternalHttpLog> queryPage = PageUtil.toMybatisPage(pageable);
        IPage<SysExternalHttpLog> page = sysExternalHttpLogMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
        return ConvertUtil.convertPage(page, SysExternalHttpLogDto.class);
    }

    @Override
    public List<SysExternalHttpLogDto> queryAll(SysExternalHttpLogQueryParam query){
        return ConvertUtil.convertList(sysExternalHttpLogMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), SysExternalHttpLogDto.class);
    }

    @Override
    public SysExternalHttpLog getById(Integer id) {
        return sysExternalHttpLogMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public SysExternalHttpLogDto findById(Integer id) {
        return ConvertUtil.convert(getById(id), SysExternalHttpLogDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(SysExternalHttpLogDto resources) {
        SysExternalHttpLog entity = ConvertUtil.convert(resources, SysExternalHttpLog.class);
        return sysExternalHttpLogMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(SysExternalHttpLogDto resources){
        SysExternalHttpLog entity = ConvertUtil.convert(resources, SysExternalHttpLog.class);
        int ret = sysExternalHttpLogMapper.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeByIds(Set<Integer> ids){
        // delCaches(ids);
        return sysExternalHttpLogMapper.deleteBatchIds(ids);
    }

    /**
     * 添加（不需要事务,保存后异常不回滚）
     * @param log
     * @return
     */
    @Override
    public int addLog(SysExternalHttpLog log) {
        return sysExternalHttpLogMapper.insert(log);
    }

    /**
     * http请求单条重传
     * @param resources
     * @return
     */
    @Override
    public int reuploadOne(SysExternalHttpLog resources) throws Exception {
        try {
            //请求结果
            String res = "";

            //请求方式 GET、POST、PUT、DELETE
            String requestMethod = resources.getRequestMethod();
            //请求地址
            String url = resources.getUrl();
            //请求参数
            String params = resources.getParams();
            //参数类型
            String paramType = resources.getParamType();

            if(DictValueEnum.METHOD_GET.getValue().equals(requestMethod)){
                //Get 请求
                res = MyHttpUtil.get(url, toMap(params));
            } else if (DictValueEnum.METHOD_POST.getValue().equals(requestMethod)) {
                //Post请求
                if(MyHttpUtil.PARAM_TYPE_FORM.equals(paramType)){
                    res = MyHttpUtil.post(url, toMap(params));
                } else {
                    res = MyHttpUtil.post(url, params);
                }
            } else if (DictValueEnum.METHOD_DELETE.getValue().equals(requestMethod)) {
                //Delete请求
                if(MyHttpUtil.PARAM_TYPE_FORM.equals(paramType)){
                    res = MyHttpUtil.delete(url, toMap(params));
                } else {
                    res = MyHttpUtil.delete(url, params);
                }
            } else if (DictValueEnum.METHOD_PUT.getValue().equals(requestMethod)) {
                //Put请求
                if(MyHttpUtil.PARAM_TYPE_FORM.equals(paramType)){
                    res = MyHttpUtil.put(url, toMap(params));
                } else {
                    res = MyHttpUtil.put(url, params);
                }
            } else {
                throw new RuntimeException("HTTP请求重传失败，系统暂不支持【】该请求方式！");
            }

            //请求成功,更新状态
            SysExternalHttpLog log = new SysExternalHttpLog();
            log.setId(resources.getId());
            log.setIsSuccess(DictValueEnum.IS_SUCCESS_Y.getValue());//成功
            log.setRequestResult(res);
            log.setRetriesNum(resources.getRetriesNum() + 1);
            sysExternalHttpLogMapper.updateById(log);

        } catch (Exception e) {
            //如果请求失败
            if(e instanceof HttpException){
                SysExternalHttpLog log = new SysExternalHttpLog();
                log.setId(resources.getId());
                log.setRetriesNum(resources.getRetriesNum() + 1);
                log.setErrorMsg(e.getMessage());
                sysExternalHttpLogMapper.updateById(log);
            }
            throw e;
        }
        return 0;
    }
    /**
     * http请求一键重传
     * @return
     */
    @Override
    public int reuploadAll() {
        //查询失败的请求
        List<SysExternalHttpLog> sysExternalHttpLogs = sysExternalHttpLogMapper.selectList(new LambdaQueryWrapper<SysExternalHttpLog>()
                .eq(SysExternalHttpLog::getIsSuccess, DictValueEnum.IS_SUCCESS_N.getValue())
                .orderByAsc(SysExternalHttpLog::getId));

        if(sysExternalHttpLogs == null || sysExternalHttpLogs.size() == 0){
            throw new RuntimeException("重传【0】条数据，没有失败的请求可操作重传！");
        }

        //成功数量
        int succeed = 0;
        //失败数量
        int unsuccessful = 0;
        //循环单条上传
        for (SysExternalHttpLog sysExternalHttpLog : sysExternalHttpLogs) {
            try {
                reuploadOne(sysExternalHttpLog);
                succeed ++;
            } catch (Exception e) {
                unsuccessful ++;
            }
        }

        if(unsuccessful != 0){
            throw new RuntimeException("重传【"+sysExternalHttpLogs.size()+"】条数据、成功【"+succeed+"】条、失败【"+unsuccessful+"】条！");
        }

        return succeed;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeById(Integer id){
        Set<Integer> set = new HashSet<>(1);
        set.add(id);
        return this.removeByIds(set);
    }

    /**
     * 转成Map对象
     * @param json
     * @return
     */
    public Map<String, Object> toMap(String json) {
        HashMap<String, Object> map = new HashMap<>();
        JSONObject jsonObject = JSONObject.parseObject(json);
        jsonObject.keySet().forEach(key -> map.put(key, jsonObject.get(key)));
        return  map;
    }

    /*
    private void delCaches(Integer id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<Integer> ids) {
        for (Integer id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<SysExternalHttpLogDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (SysExternalHttpLogDto sysExternalHttpLog : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("请求地址", sysExternalHttpLog.getUrl());
              map.put("请求参数", sysExternalHttpLog.getParams());
              map.put("请求方式", sysExternalHttpLog.getRequestMethod());
              map.put("描述", sysExternalHttpLog.getSummarize());
              map.put("错误消息", sysExternalHttpLog.getErrorMsg());
              map.put("是否成功", sysExternalHttpLog.getIsSuccess());
              map.put("重式次数", sysExternalHttpLog.getRetriesNum());
              map.put("请求结果", sysExternalHttpLog.getRequestResult());
              map.put("运行耗时", sysExternalHttpLog.getElapsedTime());
              map.put("请求时间", sysExternalHttpLog.getCreateTime());
              map.put("请求人", sysExternalHttpLog.getCreateBy());
              map.put("更新时间", sysExternalHttpLog.getUpdateTime());
              map.put("更新人", sysExternalHttpLog.getUpdateBy());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/
}
